package top.hmtools.io;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;

import top.hmtools.base.CharsetTools;

/**
 * 基于nio的操作流的工具
 * @author HyboJ
 *
 */
public class NioTools {
	
	/** 默认缓存大小 */
	public static final int DEFAULT_BUFFER_SIZE = 1024;
	/** 默认缓存大小 */
	public static final int DEFAULT_LARGE_BUFFER_SIZE = 4096;
	/** 数据流末尾 */
	public static final int EOF = -1;
	/**
     * 用于 skip() 方法的缺省缓存大小.
     */
    private static final int SKIP_BUFFER_SIZE = 2048;
    
    private static byte[] SKIP_BYTE_BUFFER;
    
    //##########################	数据流复制----开始	############################################
    
    
    /**
     * 从输入流的指定位置复制流
     * @param inputStream
     * @param outputStream
     * @param bufferSize
     * @param offSet	读取输入流的起始位置
     * @param streamProgress
     * @return
     * @throws IOException
     */
    public static long copyLarge(InputStream inputStream,OutputStream outputStream,int bufferSize,long offSet,IStreamProgress streamProgress) throws IOException{
    	IoTools.skipFully(inputStream, offSet);
    	return copyLarge(inputStream, outputStream, bufferSize, streamProgress);
    }
    
    /**
     * 复制流
     * @param inputStream
     * @param outputStream
     * @param bufferSize
     * @param streamProgress
     * @return
     * @throws IOException
     */
    public static long copyLarge(InputStream inputStream,OutputStream outputStream,int bufferSize,IStreamProgress streamProgress) throws IOException{
    	return copyLarge(Channels.newChannel(inputStream), Channels.newChannel(outputStream), bufferSize, streamProgress);
    }
	
    /**
     * 复制流
     * @param inChannel	输入流通道
     * @param outChannel	输出流通道
     * @param bufferSize	缓存大小
     * @param streamProgress	复制流进度条
     * @return
     * @throws IOException
     */
	public static long copyLarge(ReadableByteChannel inChannel, WritableByteChannel outChannel, int bufferSize, IStreamProgress streamProgress) throws IOException{
		//设置缓冲区
		ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize <= 0 ? DEFAULT_LARGE_BUFFER_SIZE : bufferSize);
		
		//复制流的总字节数
		long count = 0;
		
		if (null != streamProgress) {
			streamProgress.start();
		}
		
		//复制流
		while (inChannel.read(byteBuffer) != EOF) {
			byteBuffer.flip();// 写转读
			count += outChannel.write(byteBuffer);
			byteBuffer.clear();
			
			if (null != streamProgress) {
				streamProgress.progress(count);
			}
		}
		
		if (null != streamProgress) {
			streamProgress.finish();
		}
		
		return count;
	}
	
	//##########################	数据流复制----结束	############################################

	
	//##########################	数据流读取----开始	############################################
	
	/**
	 * 读取数据流到byte数组
	 * @param inputStream
	 * @param bufferSize
	 * @param streamProgress
	 * @return
	 * @throws IOException
	 */
	public static byte[] readToByte(InputStream inputStream,int bufferSize,IStreamProgress streamProgress) throws IOException{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		copyLarge(inputStream, baos, bufferSize, streamProgress);
		byte[] result = baos.toByteArray();
		return result;
	}
	
	/**
	 *  读取数据流到byte数组
	 * @param inputStream
	 * @param streamProgress
	 * @return
	 * @throws IOException
	 */
	public static byte[] readToByte(InputStream inputStream,IStreamProgress streamProgress) throws IOException{
		return readToByte(inputStream, DEFAULT_LARGE_BUFFER_SIZE, streamProgress);
	}
	
	/**
	 * 读取数据流到字符串，并制定字符编码。
	 * <br>缺省使用当前操作系统缺省字符编码（windows 时 GBK，UNIX 是 utf-8）
	 * @param input
	 * @param charset
	 * @return
	 * @throws IOException
	 */
	public static String readToString(final InputStream input,Charset charset) throws IOException{
		byte[] resultBytes = readToByte(input, null);
		String result = new String(resultBytes, charset==null?CharsetTools.defaultCharset():charset);
		return result;
	}
	
	/**
	 * 读取数据流到字符串，以utf-8字符编码
	 * @param input
	 * @return
	 * @throws IOException
	 */
	public static String readToStringUTF8(final InputStream input) throws IOException{
		return readToString(input, CharsetTools.CHARSET_UTF_8);
	}
	
	
	//##########################	数据流读取----结束	############################################

	//##########################	数据流写入----开始	############################################
	
	
	
	//##########################	数据流写入----结束	############################################

}
